
#include <BHBoxLayout>
#include <BTableItem>
#include <BListItem>
#include <BLineEdit>
#include <BClass>

#include "StringUtils.h"
#include "ScriptFormat.h"
#include "VariantBoard.h"

VariantBoard::VariantBoard(BWidget* parent) : BWidget(parent)
{
	_stackWidget = new BTableWidget();
	_stackWidget->setColumnCount(3);
	_stackWidget->setColumnLabel(0, "type");
	_stackWidget->setColumnLabel(1, "name");
	_stackWidget->setColumnLabel(2, "value");
	_stackWidget->setColumnWidth(0, 100);
	_stackWidget->setColumnWidth(1, 200);
	_stackWidget->setColumnWidth(2, 200);
	_stackWidget->setSelectMode(Select_Rows | Select_Single);
	//_stackWidget->setColumnPolicy(Policy_Preferred | Policy_Expanding);
	_stackWidget->setGridStyle(Grid_Crossing);

	_treeWidget = new BTreeWidget();
	_treeWidget->setTitleVisible(true);

	BHBoxLayout* hlayout = new BHBoxLayout(this);
	hlayout->addWidget(_stackWidget);
	hlayout->addWidget(_treeWidget);
	hlayout->setSplitable(true);
	hlayout->setSpacing(4);

	connect(this, Signal_AssetChanged, &VariantBoard::slotAssetChanged);

	connect(_stackWidget, Signal_ItemInserted, &VariantBoard::slotStackItemInserted);
	connect(_stackWidget, Signal_ItemRemoved, &VariantBoard::slotStackItemRemoved);
	connect(_stackWidget, Signal_ItemSelected, &VariantBoard::slotStackItemSelected);
}
VariantBoard::~VariantBoard()
{

}

void VariantBoard::freshStack()
{
	BString text;
	BString type;
	BString name;
	_stackWidget->setRowCount(_script->stackSize());
	for (int i = 0; i < _script->stackSize(); i++)
	{
		const BValue& value = _script->stack(i, type, name);
		_stackWidget->setRowAsset(i, value);
		_stackWidget->setRowLabel(i, i);
		if (BExp* exp = value)
		{
			switch (exp->syntax)
			{
			case Syntax_Begin:
				_stackWidget->setItem(i, 0, "begin");
				_stackWidget->setItem(i, 1, "----------------------");
				_stackWidget->setItem(i, 2, StringOfValue(exp->value));
				break;
			default:
				_stackWidget->setItem(i, 0, "exp:unknown");
				break;
			}
		}
		else
		{
			_stackWidget->setItem(i, 0, type);
			_stackWidget->setItem(i, 1, name);
			text.reset();
			if (const BValue* ptr = value)
			{
				text << "->" << name;
			}
			else
			{
				if (BClass* cls = value)
					text << "ref_count : " << cls->ref_count();
				else
					text << StringOfValue(value.refer());
			}
			_stackWidget->setItem(i, 2, text);
		}
		//BTableItem* item0 = _stackWidget->item(i, 0);
		//if (item0 && item0->textFormat() == 0)
		//{
		//	ScriptFormat* format = new ScriptFormat();
		//	format->setScript(_script);
		//	item0->setTextFormat(format);
		//}
		//BTableItem* item1 = _stackWidget->item(i, 2);
		//if (item1 && item1->textFormat() == 0)
		//{
		//	ScriptFormat* format = new ScriptFormat();
		//	format->setScript(_script);
		//	item1->setTextFormat(format);
		//}
	}
	int lastRow = _stackWidget->rowCount() - 1;
	BTableItem* item = _stackWidget->item(lastRow, 0);
	_stackWidget->scrollToItem(item);

	_treeWidget->clearItems();
	if (BTableItem* selectedItem = _stackWidget->selectedItem())
	{
		Variant variant;
		variant.value = _script->stack(selectedItem->row(), variant.type, variant.name);
		BTreeItem* item = createTreeItem(variant);
		_treeWidget->addItem(item);
	}

}
BTreeItem* VariantBoard::createTreeItem(const Variant& variant)
{
	if (BClass* cls = variant.value)
	{
		BTreeItem* clsItem = new BTreeItem();
		BString text = variant.type;
		text << ' ' << variant.name;
		if (variant.type.beginWith("array<"))
		{
			const BValueArray& array = cls->asset();
			BString str(array.size());
			text << '[' << str << ']';
			for (int i = 0; i < array.size(); i++)
			{
				str.reset();
				str << '[' << i << "]\t" << StringOfValue(array[i]);
				clsItem->addChild(str);
			}
		}
		clsItem->setText(text);
		for (int i = 0; i < cls->variantCount(); i++)
		{
			const BValue& variant = cls->variant(i);
			BTreeItem* child = createTreeItem(variant);
			clsItem->addChild(child);
		}
		return clsItem;
	}
	if (BObject* obj = variant.value)
	{
		BString text = variant.type;
		text << "* " << variant.name << '(' << obj->ref_count() << ')';
		BTreeItem* objItem = new BTreeItem(text);
		return objItem;
	}
	if (BExp* exp = variant.value)
	{
		BString text = exp->type;
		text << ' ' << exp->name;
		text << " : " << StringOfValue(exp->value);
		BTreeItem* item = new BTreeItem(text);
		return item;
	}
	BString text = variant.type;
	text << ' ' << variant.name;
	text << " : " << StringOfValue(variant.value.refer());
	BTreeItem* item = new BTreeItem(text);
	return item;
}

void VariantBoard::slotAssetChanged(BObject* object, const BValue& value)
{
	BScript* script = value;
	if (_script != script)
	{
		_script = script;
	}
}
void VariantBoard::slotStackItemInserted(BObject* object)
{
	int lastRow = _stackWidget->rowCount() - 1;
	BTableItem* item = _stackWidget->item(lastRow, 0);
	_stackWidget->scrollToItem(item);
}
void VariantBoard::slotStackItemRemoved(BObject* object)
{
	int lastRow = _stackWidget->rowCount() - 1;
	BTableItem* item = _stackWidget->item(lastRow, 0);
	_stackWidget->scrollToItem(item);
}
void VariantBoard::slotStackItemSelected(BObject* object, const BValue& value)
{
	BTableItem* item = value;
	_treeWidget->clearItems();
	if (item->selected())
	{
		Variant variant;
		variant.value = _script->stack(item->row(), variant.type, variant.name);
		BTreeItem* item = createTreeItem(variant);
		_treeWidget->addItem(item);
	}
}

